package com.info.pan.schedule;

import com.info.pan.core.exception.HPanFrameworkException;
import com.info.pan.core.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

@Slf4j
@Component
public class ScheduleManager {

    private final ThreadPoolTaskScheduler taskScheduler;

    private Map<String, ScheduleTaskHolder> cache = new ConcurrentHashMap<>();

    public ScheduleManager(ThreadPoolTaskScheduler taskScheduler) {
        this.taskScheduler = taskScheduler;
    }

    /**
     * 启动一个定时任务
     *
     * @param task 定时任务
     * @param cron cron表达式
     * @return
     */
    public String startTask(ScheduleTask task, String cron) {
        ScheduledFuture<?> scheduledFuture = taskScheduler.schedule(task, new CronTrigger(cron));
        String key = UUIDUtil.getUUID();
        ScheduleTaskHolder holder = new ScheduleTaskHolder(task, scheduledFuture);
        cache.put(key, holder);
        log.info("{} 启动成功！唯一标识为 {}", task.getName(), key);
        return key;
    }

    /**
     * 停止一个定时任务
     *
     * @param key
     */
    public void stopTask(String key) {
        if (StringUtils.isBlank(key)) {
            return;
        }
        ScheduleTaskHolder holder = cache.get(key);
        if (holder == null) {
            return;
        }
        ScheduledFuture scheduledFuture = holder.getScheduledFuture();
        boolean cancel = scheduledFuture.cancel(true);
        if (cancel) {
            log.info("{} 停止成功！ 唯一标识为 {}", holder.getScheduleTask().getName(), key);
        } else {
            log.info("{} 停止失败！ 唯一标识为 {}", holder.getScheduleTask().getName(), key);
        }
    }

    /**
     * 更新定时任务的执行时间
     *
     * @param key
     * @param cron
     * @return
     */
    public String changeTask(String key, String cron) {
        if (StringUtils.isAnyBlank(key, cron)) {
            throw new HPanFrameworkException("定时任务的唯一标识以及新的执行表达式不能为空！");
        }
        ScheduleTaskHolder holder = cache.get(key);
        if (holder == null) {
            throw new HPanFrameworkException("未匹配到对应的定时任务");
        }
        stopTask(key);
        return startTask(holder.getScheduleTask(), cron);
    }
}
